﻿/*
 *************************************
 * Tipper: News Scroller
 * http://www.FlepStudio.org         
 * © Author: Filippo Lughi           
 * version 1.0                       
 *************************************
 */
package org.FlepStudio.Tipper
{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import Main;
	
	/**
	 * IphoneScroller is a ValueObject for the FlepStudio API.
	 * This class reproduces the Apple Iphone scrolling effect
	 *
	 * @author Filippo Lughi
	 * @version Actionscript 3.0
	 */
	public class IphoneScroller extends MovieClip
	{
		private var content:DisplayObject;
		private var scrollV:MovieClip;
		private var scrollH:MovieClip;
		private var mask_mc:Shape;
		private var isDragging:Boolean=false;
		private var lastP:Point=new Point();
		private var firstP:Point=new Point();
		private var firstPanelP:Point=new Point();
		private var diff:Point=new Point();
		private var inertia:Point=new Point();
		private var min:Point=new Point();
		private var max:Point=new Point();
		private var widthView:Number;
		private var heightView:Number;
		private var totalX:Number;
		private var totalY:Number;
		
		private var _scrollRatio:Number=10;
		private var _v:Boolean=true;
		private var _h:Boolean=true;
		
		/**
		 * Construct a new IphoneScroller instance
		 *
		 * @param		.content		DisplayObject          -- the object to scroll
		 * @param		.w				Number          	   -- width of view zone
		 * @param		.h				Number                 -- height of view zone
		 * @param		.i				Main                 	-- instantie van de stage
		 */
		public function IphoneScroller(content:DisplayObject,w:Number,h:Number,i:Main)
		{
			widthView=w;
			heightView=h;
			trace("test");
			trace(Main.getinstance());
			graphics.beginFill(0,0);
			graphics.drawRect(0,0,width,height);
			graphics.endFill();
			
			this.content=content;
			addChild(content);
			
			addEventListener(Event.ADDED_TO_STAGE,init);
			addEventListener(Event.REMOVED,destroy);
		}
		
		/**
		 * Width of view zone
		 */
		public function get v():Boolean
		{
			return _v;
		}
		
		public function set v(b:Boolean):void
		{
			_v=b;
		}
		
		/**
		 * Height of view zone
		 */
		public function get h():Boolean
		{
			return _h;
		}
		
		public function set h(b:Boolean):void
		{
			_h=h;
		}
		
		/**
		 * Factor of the scroller ratio
		 */
		private function get scrollRatio():Number
		{
			return _scrollRatio;
		}
		
		private function set scrollRatio(n:Number):void
		{
			_scrollRatio=n;
		}
		
		private function init(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init);
			addEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown);
			addEventListener(Event.ENTER_FRAME,handleEnterFrame);
			
			
			createMask();
			createScrolls();
		}
		
		private function createMask():void
		{
			mask_mc=new Shape();
			mask_mc.graphics.beginFill(0xFF0033,1);
			mask_mc.graphics.drawRect(0,0,widthView,heightView);
			mask_mc.graphics.endFill();
			content.mask=mask_mc;
			addChild(mask_mc);
		}
		
		private function createScrolls():void
		{
			scrollV=new MovieClip();
			scrollV.cacheAsBitmap=true;
			scrollV.x=widthView-10;
			addChild(scrollV);
			
			scrollH=new MovieClip();
			scrollH.cacheAsBitmap=true;
			scrollH.y=heightView-10;
			addChild(scrollH);
		}
		
		private function handleMouseMove(e:MouseEvent):void
		{
			totalX=mouseX-firstP.x;
			totalY=mouseY-firstP.y;
			
			if(v&&Math.abs(totalY)>scrollRatio)
				isDragging=true;
			if(h&&Math.abs(totalX)>scrollRatio)
				isDragging=true;
				
			checkIsDragging();
		}
		
		private function checkIsDragging():void
		{
			if(isDragging)
			{
				if(v)
				{
					if(totalY<min.y)
						totalY=min.y-Math.sqrt(min.y-totalY);
					if(totalY>max.y)
						totalY=max.y+Math.sqrt(totalY-max.y);
					
					content.y=firstPanelP.y+totalY;
				}
				
				if(h)
				{
					if(totalX<min.x)
						totalX=min.x-Math.sqrt(min.x-totalX);
					if(totalX>max.x)
						totalX=max.x+Math.sqrt(totalX-max.x);
					
					content.x=firstPanelP.x+totalX;
				}
			}
		}
		
		private function handleMouseUp(e:MouseEvent):void
		{
			if(stage.hasEventListener(MouseEvent.MOUSE_MOVE))
				stage.removeEventListener(MouseEvent.MOUSE_MOVE,handleMouseMove);
			isDragging=false;
			
			if(v)
				inertia.y=diff.y;
			if(h)
				inertia.x=diff.x;
			
			stage.removeEventListener(MouseEvent.MOUSE_UP,handleMouseUp);
		}
		
		private function handleMouseDown(e:MouseEvent):void
		{
			if(!stage.hasEventListener(MouseEvent.MOUSE_MOVE))
			{
				stage.addEventListener(MouseEvent.MOUSE_MOVE,handleMouseMove);
				stage.addEventListener(MouseEvent.MOUSE_UP,handleMouseUp);
			}
			
			inertia.y=0;
			inertia.x=0;
			
			firstP.x=mouseX;
			firstP.y=mouseY;
			
			firstPanelP.x=content.x;
			firstPanelP.y=content.y;
			
			min.x=Math.min(-content.x,-content.width+widthView-content.x);
			min.y=Math.min(-content.y,-content.height+heightView-content.y);
			
			max.x=-content.x;
			max.y=-content.y;
			
			scrollV.graphics.clear();
			
			if(v)
			{
				scrollV.graphics.beginFill(0x888899,.5);
				scrollV.graphics.drawRoundRect(2,0,6,heightView*Math.max(0,heightView/content.height),8);
				scrollV.graphics.endFill();
			}
			
			scrollH.graphics.clear();
			
			if(h)
			{
				scrollH.graphics.beginFill(0x888899,.5);
				scrollH.graphics.drawRoundRect(0,2,widthView*Math.max(0,widthView/content.width),6,8);
				scrollH.graphics.endFill();
			}
		}
		
		private function handleEnterFrame(e:Event):void
		{
			diff.y=mouseY-lastP.y;
			diff.x=mouseX-lastP.x;
			
			lastP.y=mouseY;
			lastP.x=mouseX;
			
			if(!isDragging)
			{
				if(v)
				{
					if(content.y>0)
					{
						inertia.y=0;
						content.y*=0.8;
						if(content.y<1)
							content.y=0;
					}
					
					if(content.height>=heightView&&content.y<heightView-content.height)
					{
						inertia.y=0;
						
						var goal:Number=heightView-content.height;
						var diff:Number=goal-content.y;
						
						if(diff>1)
							diff*=0.2;
						
						content.y+=diff;
					}
					
					if(content.height<heightView&&content.y<0)
					{
						inertia.y=0;
						content.y*=0.8;
						
						if(content.y>-1)
							content.y=0;
					}
					
					if(Math.abs(inertia.y)>1)
					{
						content.y+=inertia.y;
						inertia.y*=0.95;
					}
					else
						inertia.y=0;
					
					if(inertia.y!=0)
					{
						if(scrollV.alpha<1)
							scrollV.alpha=Math.min(1,scrollV.alpha+0.1);
						scrollV.y=heightView*Math.min(1,(-content.y/content.height));
					}
					else
					{
						if(scrollV.alpha>0)
							scrollV.alpha=Math.max(0,scrollV.alpha-0.1);
					}
				}
				
				if(h)
				{
					if(content.x>0)
					{
						inertia.x=0;
						content.x*=0.8;
						
						if(content.x<1)
							content.x=0;
					}
					
					if(content.width>=widthView&&content.x<widthView-content.width)
					{
						inertia.x=0;
						
						goal=widthView-content.width;
						diff=goal-content.x;
						
						if(diff>1)
							diff*=0.2;
						
						content.x+=diff;
					}
					
					if(content.width<widthView&&content.x<0)
					{
						inertia.x=0;
						content.x*=0.8;
						
						if(content.x>-1)
							content.x=0;
					}
					
					if(Math.abs(inertia.x)>1)
					{
						content.x+=inertia.x;
						inertia.x*=0.95;
					}
					else
						inertia.x=0;
					
					if(inertia.x!=0)
					{
						if(scrollH.alpha<1)
							scrollH.alpha=Math.min(1,scrollH.alpha+0.1);
						
						scrollH.x=widthView*Math.min(1,(-content.x/content.width));
					}
					else
					{
						if(scrollH.alpha>0)
							scrollH.alpha=Math.max(0,scrollH.alpha-0.1);
					}
				}
			}
			else
			{
				if(v)
				{
					if(scrollV.alpha<1)
						scrollV.alpha=Math.min(1,scrollV.alpha+0.1);
					
					scrollV.y=heightView*Math.min(1,(-content.y/content.height));
				}
				
				if(h)
				{
					if(scrollH.alpha<1)
						scrollH.alpha=Math.min(1,scrollH.alpha+0.1);
					
					scrollH.x=widthView*Math.min(1,(-content.x/content.width));
				}
			}
		}
		
		private function destroy(evt:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init);
			removeEventListener(Event.REMOVED,destroy);
			removeEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown);
			removeEventListener(Event.ENTER_FRAME,handleEnterFrame);
		}
	}
}